package com.cashbird.app.infra.utils

import androidx.lifecycle.DefaultLifecycleObserver
import androidx.lifecycle.Lifecycle
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.coroutineScope
import com.adwin.addcoin.utils.log
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.channels.BufferOverflow
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableSharedFlow
import kotlinx.coroutines.flow.asSharedFlow
import kotlinx.coroutines.launch
import kotlin.collections.mutableMapOf
import kotlin.collections.set

/**
 * @Author FenLJ
 * @Date 2022/7/29-14:24
 * @Email nunu.feng@backgardon.com
 * 基于Flow和LifeCycle的事件总线
 **/
object FlowBus {
    const val TAG = "FlowBus"
    private val busMap = mutableMapOf<String, EventBus<*>>()
    private val busStickMap = mutableMapOf<String, StickEventBus<*>>()

    @Synchronized
    fun <T> with(key: String): EventBus<T> {
        var eventBus = busMap[key]
        if (eventBus == null) {
            eventBus = EventBus<T>(key)
            busMap[key] = eventBus
        }
        return eventBus as EventBus<T>
    }

    @Synchronized
    fun <T> withStick(key: String): StickEventBus<T> {
        var eventBus = busStickMap[key]
        if (eventBus == null) {
            eventBus = StickEventBus<T>(key)
            busStickMap[key] = eventBus
        }
        return eventBus as StickEventBus<T>
    }

    // 真正实现类
    open class EventBus<T>(private val key: String) : DefaultLifecycleObserver {

        // 私有对象用于发送消息
        private val _events: MutableSharedFlow<T> by lazy {
            obtainEvent()
        }

        // 暴露的公有对象用于接收消息
        val events = _events.asSharedFlow()

        open fun obtainEvent(): MutableSharedFlow<T> = MutableSharedFlow(0, 1, BufferOverflow.DROP_OLDEST)

        // 主线程接收数据
        fun register(lifecycle: Lifecycle, action: (t: T) -> Unit) {
            lifecycle.addObserver(this)
            lifecycle.coroutineScope.launch {
                events.collect {
                    try {
                        "On Event [$key] Collect:$it".log(TAG)
                        action(it)
                    } catch (e: Exception) {
                        "On Event [$key] Error:$e".log(TAG)
                        e.printStackTrace()
                    }
                }
            }
        }

        // 协程中发送数据
        suspend fun post(event: T) {
            "On Event [$key] Post By Coroutine:$event".log(TAG)
            _events.emit(event)
        }

        // 协程中延迟发送数据
        suspend fun post(event: T,delay: Long = 0L){
            if(delay > 0L) delay(delay)
            _events.emit(event)
        }

        // 主线程发送数据
        fun post(scope: CoroutineScope, event: T) {
            scope.launch {
                "On Event [$key] Post By Main Thread:$event".log(TAG)
                _events.emit(event)
            }
        }

        // 主线程发送数据
        fun post(lifecycle: Lifecycle, event: T, delay: Long = 0L) {
            lifecycle.coroutineScope.launch {
                if (delay != 0L) delay(delay)
                "On Event [$key] Post By Main Thread:$event".log(TAG)
                _events.emit(event)
            }
        }

        // 跟随生命周期自动销毁
        override fun onDestroy(owner: LifecycleOwner) {
            super.onDestroy(owner)
            val subscriptCount = _events.subscriptionCount.value
            if (subscriptCount <= 0)
                busMap.remove(key)
        }

    }

    class StickEventBus<T>(key: String) : EventBus<T>(key) {
        override fun obtainEvent(): MutableSharedFlow<T> = MutableSharedFlow(1, 1, BufferOverflow.DROP_OLDEST)
    }

}